#ifndef GETSECTION_H
#define GETSECTION_H
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "getpidpackage.h"

#define INITIAL_VERSION 0xffff

#define SECTION_COUNT_256 256
#define PACKAGE_MAX_LENGTH_204 204
#define SECTION_MAX_LENGTH_4096 1024*4

typedef struct SECTION_HEAD
{
    unsigned int table_id :8;
    unsigned int section_syntax_indicator :1;
    unsigned int zero :1;
    unsigned int reserved_1 :2;
    unsigned int section_length :12;
    unsigned int table_id_extension :16;
    unsigned int reserved_2 :2;
    unsigned int version_number :5;
    unsigned int current_next_indicator :1;
    unsigned int section_number :8;
    unsigned int last_section_number :8;
} SECTION_HEAD;


class GetSection
{
public:
    ~GetSection();
    GetSection(const GetSection&)=delete;
    GetSection& operator=(const GetSection&)=delete;
    static GetSection& get_instance();

    /*********************************************************************************************************************************
     * Function Name : GetOneSection
     * Description   :  get one section
     * Parameters    :
     * 				pfTsFile -- the TS file descriptor
     * 				iTsLength -- the TS package length
     *				pucSectionBuffer -- the section buffer
     *				uiWantPID -- the PID which we want
     *				uiTableId -- the table id which we want
     *				uiTableIdExtension -- the table id extension
     *				puiVersion -- the record version number
     * Returns       : -1 - reach the file end 0 - the version change 1 - one section over
     *********************************************************************************************************************************/
    int GetOneSection(FILE *pfTsFile, int iTsLength, unsigned char *pucSectionBuffer, unsigned int uiPID, unsigned int uiTableId,
            unsigned int *puiVersion);

    /*********************************************************************************************************************************
     * Function Name : GetEIT_OneSection
     * Description   :  get the EIT one section(we should point the table_id_extension)
     * Parameters    :
     * 				pfTsFile -- the TS file descriptor
     * 				iTsLength -- the TS package length
     *				pucSectionBuffer -- the section buffer
     *				uiTableId -- the table id which we want
     *				uiTableIdExtension -- the table id extension (the program number which we want to know the EIT information)
     *				puiVersion -- the record version number
     * Returns       : -1 - reach the file end 0 - the version change 1 - one section over
     *********************************************************************************************************************************/
    int GetEIT_OneSection(FILE *pfTsFile, int iTsLength, unsigned char *pucSectionBuffer, unsigned int uiTableId, unsigned uiTableIdExtension,
            unsigned int *puiVersion);

    /*********************************************************************************************************************************
     * Function Name : IsSectionGetBefore
     * Description   :  is the section number has been get before
     * Parameters    :
     * 				pucSectionBuffer -- the section buffer
     * 				puiRecordSectionNumber -- record the section number and the section count
     * Returns       : 1 - the section already get  0 - do not get
     *********************************************************************************************************************************/
    int IsSectionGetBefore(unsigned char *pucSectionBuffer, unsigned int *puiRecordSectionNumber);

    /*********************************************************************************************************************************
     * Function Name : IsAllSectionOver
     * Description   :  is all the section is over
     * Parameters    :
     *				pucSectionBuffer -- the section buffer
     *				puiRecordSectionNumber -- the buffer record the parse section number and the section count
     * Returns       : 1 - all section over 0 - do not over
     *********************************************************************************************************************************/
    int IsAllSectionOver(unsigned char *pucSectionBuffer, unsigned int *puiRecordSectionNumber);

private:
    /*********************************************************************************************************************************
     * Function Name : GetTheLoadBeginPostion
     * Description   :  get the package load begin position
     * Parameters    :
     *				pucPackageBuffer -- the package buffer
     * Returns       : -1 - get error >=0 - success
     *********************************************************************************************************************************/
    int GetTheLoadBeginPostion(unsigned char *pucPackageBuffer);
    /*********************************************************************************************************************************
     * Function Name : PutTheBufferToSection
     * Description   :  put the buffer to the section
     * Parameters    :
     *				pucSectionBuffer -- the section buffer where we put buffer
     *				pucPackageBuffer -- the package buffer
     *				piAlreadyAddSection -- the already add length before
     *				pstSectionHead -- the section head structure
     * Returns       : void
     *********************************************************************************************************************************/
    void PutTheBufferToSection(unsigned char *pucSectionBuffer, unsigned char *pucPackageBuffer, int *piAlreadyAddSection,
            SECTION_HEAD *pstSectionHead);

    /*********************************************************************************************************************************
     * Function Name :  ParseSectionHeader
     * Description   :  parse the section head
     * Parameters    :
     * 				pstSectionHead -- the section head
     *				pucPackageBuffer -- the package buffer
     * Returns       : void
     *********************************************************************************************************************************/
    void ParseSectionHeader(SECTION_HEAD *pstSectionHead, unsigned char *pucPackageBuffer);
    /*********************************************************************************************************************************
     * Function Name : IsVersionChange
     * Description   :  judgment whether the version number change (if version is 0xff we should record new version number)
     * Parameters    :
     *				stSectionHead -- the section head structure
     *				puiRecordVersion -- the previous version number
     * Returns       : 1 - version number change 0 - version number not change
     *********************************************************************************************************************************/
    int IsVersionChange(SECTION_HEAD *pstSectionHead, unsigned int *puiRecordVersion);
    /*********************************************************************************************************************************
     * Function Name : IsOneSectionOver
     * Description   :  is one section is over
     * Parameters    :
     * 				stSectionHead -- the section head structure
     * 				iAddLength -- the add length of the section
     * Returns       : 1 - one section over 0 - not over
     *********************************************************************************************************************************/
    int IsOneSectionOver(SECTION_HEAD stSectionHead, int iAddLength);
private:
    GetSection();
};

#endif // GETSECTION_H
